package com.tran.demo.controller;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.google.common.util.concurrent.RateLimiter;
import com.tran.demo.entity.Person;
import com.tran.demo.service.IPersonService;
import com.tran.demo.utils.RetResponse;
import com.tran.demo.utils.RetResult;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author com
 * @since 2019-03-15
 */
@RestController
@RequestMapping("/person")
public class PersonController{


	private final static Logger log = org.slf4j.LoggerFactory.getLogger(PersonController.class);

	private static final RateLimiter rateLimiter = RateLimiter.create(1);

	private  static int  count = 0;

	@Autowired
	private IPersonService personSerivce;

	@GetMapping("/query/all")
	@ResponseBody
	public RetResult<List<Person>> getAllPerson() {
		Wrapper<Person> person = new EntityWrapper<Person>();
		return RetResponse.makeOKRsp(personSerivce.selectList(person));
	}

	@RequestMapping(value = "/insert", method = RequestMethod.POST)
	public RetResult insert(@RequestBody Person person) throws InterruptedException, ExecutionException {
		CountDownLatch count = new CountDownLatch(100000);
		int corePoolSize = 100;
		int maximumPoolSize = 2000;
		int keepAliveTime = 1000;
		TimeUnit unit = TimeUnit.SECONDS;
		LinkedBlockingQueue queue = new LinkedBlockingQueue<>();
		ThreadPoolExecutor pool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, queue);
		log.info("线程池插入开始时间：{}", LocalDateTime.now());

		for (int i = 0; i < 100000; i++) {
			int id = i;
			pool.submit(new Runnable() {
				@Override
				public void run() {
					person.setId(id);
					personSerivce.insert(person);
				}
			});
			count.countDown();
		}
		try {
			count.await();
		} catch (InterruptedException e) {
			log.error("发生错误：{}", e);
		}
		if (log.isInfoEnabled()) {
			log.info("线程池插入结束时间：{}", LocalDateTime.now());
		}
		return RetResponse.makeOKRsp();
	}

	@RequestMapping(value = "/insert1", method = RequestMethod.POST)
	public RetResult insert1(@RequestBody Person person) throws InterruptedException, ExecutionException {
		log.info("单线程循环插入开始时间：{}", LocalDateTime.now());
		for (int i = 0; i < 100000; i++) {
			personSerivce.insert(person);
		}
		log.info("单线程循环插入结束时间：{}", LocalDateTime.now());
		return RetResponse.makeOKRsp();
	}

	@RequestMapping(value = "/delayed", method = RequestMethod.POST)
	public RetResult delayed() {
		int corePoolSize = 10;
		ScheduledThreadPoolExecutor sPool = new ScheduledThreadPoolExecutor(corePoolSize);

		sPool.schedule(new Runnable() {
			@Override
			public void run() {
				log.info("延时任务开始执行：");
				personSerivce.insert(new Person(1111, "张三", 12, "后海"));
			}
		}, 10, TimeUnit.SECONDS);

		return RetResponse.makeOKRsp();
	}

	@RequestMapping(value = "/rateLimiter", method = RequestMethod.POST)
	private static void rateLimiter() {

		if (!rateLimiter.tryAcquire()) {
			log.info("限流中");
			return;
		}
		log.info("成功获取令牌，执行业务");
	}

	public static void main(String[] args) throws InterruptedException {
		CountDownLatch num = new CountDownLatch(10000);
		int corePoolSize = 1000;
		int maximumPoolSize = 2000;
		int keepAliveTime = 1000;
		TimeUnit unit = TimeUnit.SECONDS;
		LinkedBlockingQueue queue = new LinkedBlockingQueue<>();
		ThreadPoolExecutor pool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, queue);
		
		for(int i=0;i<10000;i++) {
			pool.submit(new Runnable() {
				@Override
				public void run() {
					add();
					num.countDown();
				}
			});
		}
		
		num.await();
		System.out.println("总和："+count);
	}
	private static  void add() {
		count++;
	}

}
